package com.nova.pro.opengl.render;

import android.opengl.GLES20;
import android.opengl.GLSurfaceView;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

/**
 * Created by Administrator on 2017-11-29.
 *
 * @author kzaxil
 * @since 1.1.0
 */
public class TriangleRender implements GLSurfaceView.Renderer {
    private final String vertexShaderCode =
            "attribute vec4 vPosition;    \n" +
                    "void main() {                \n" +
                    "    gl_Position = vPosition; \n" +
                    "}                            \n";

    private final String fragmentShaderCode =
            "precision mediump float;    \n" +
                    "uniform vec4 vColor;        \n" +
                    "void main() {               \n" +
                    "    gl_FragColor = vColor;  \n" +
                    "}                           \n";

    private float triangleCoords[] = {
            0.5f, 0.5f, 0.0f, // top
            -0.5f, -0.5f, 0.0f, // bottom left
            0.5f, -0.5f, 0.0f  // bottom right
    };

    private int mProgram;
    private FloatBuffer vertexBuffer;

    static final int COORDS_PER_VERTEX = 3;
    // 顶点个数
    private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
    // 顶点之间的偏移量
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 每个顶点四个字节

    private int loadShader(int type, String shaderCode) {
        // 根据type创建顶点着色器或者片元着色器
        int shader = GLES20.glCreateShader(type);
        // 将资源加入到着色器中，并编译
        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);
        return shader;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        GLES20.glClearColor(0f, 0f, 0f, 1f);
        // 申请底层空间，每个float占4字节
        ByteBuffer bb = ByteBuffer.allocateDirect(triangleCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());
        // 将坐标数据转换为FloatBuffer，用以传入给OpenGL ES程序
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(triangleCoords);
        vertexBuffer.position(0);

        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

        // 创建一个空的OpenGLES程序
        mProgram = GLES20.glCreateProgram();
        // 将顶点着色器加入到程序
        GLES20.glAttachShader(mProgram, vertexShader);
        // 将片元着色器加入到程序中
        GLES20.glAttachShader(mProgram, fragmentShader);
        // 连接到着色器程序
        GLES20.glLinkProgram(mProgram);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES20.glViewport(0, 0, width, height);// 设置视图窗口
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        // 将程序加入到OpenGLES2.0环境
        GLES20.glUseProgram(mProgram);

        // 获取顶点着色器的vPosition成员句柄
        int position = GLES20.glGetAttribLocation(mProgram, "vPosition");
        // 启用三角形顶点的句柄
        GLES20.glEnableVertexAttribArray(position);
        // 准备三角形的坐标数据
        GLES20.glVertexAttribPointer(position, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);

        // 获取片元着色器的vColor成员的句柄
        int location = GLES20.glGetUniformLocation(mProgram, "vColor");
        float color[] = {1.0f, 1.0f, 1.0f, 1.0f}; // 白色
        // 设置绘制三角形的颜色
        GLES20.glUniform4fv(location, 1, color, 0);
        // 绘制三角形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
        // 禁止顶点数组的句柄
        GLES20.glDisableVertexAttribArray(position);
    }
}
